// ==UserScript==
// @name         Heist Artwork
// @description  Save or upload artwork on discogs.com
// @version      0.1
// @match        https://www.hardstyle.com/*
// @include      /https://www\.hardtunes\.[\S]/*/
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @license      WTFPL
// @downloadURL  https://notabug.org/Collector/Heist-Artwork/raw/master/script.user.js
// ==/UserScript==

(() => {
	'use strict';

	const MAX_SIZE = 4194304; // 4 MB
	const COMMENT = 'Uploaded via script.';

	const getMaxSize = url => {
		return `https://tracks.content.hardstyle.com/products/${url.replace(/^https:\/\/tracks\.content\.hardstyle\.com\/products\/(\d+)\/(\d+)\/(\d+)[/?][\S\s]*|$/, '$1/$2/$3')}/original.jpg`;
	};

	function gmRequest(object) {
		return new Promise((resolve, reject) => {
			GM_xmlhttpRequest(Object.assign(object, {
				onload: r => resolve(r),
				onerror: r => reject(r)
			}));
		});
	}

	function notify(msg) {
		const title = GM_info.script.name + ' ' + GM_info.script.version;
		GM_notification({
			text: msg,
			title,
			timeout: 5000
		});
	}

	function saveImage(releaseId, imageId) {
		return gmRequest({
			method: 'POST',
			url: `https://www.discogs.com/release/${releaseId}/images/save`,
			headers: {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
			data: `id=${releaseId}&type=release&active_images=${imageId}&disabled_images=&comment=${COMMENT}&is_pending=false`
		}).then(r => {
			if (r.status === 200 && !r.finalUrl.includes('nologin')) {
				return 'Image saved!';
			}

			return 'Failed save image. You must be logged!';
		}).catch(error => error.message);
	}

	function uploadImage(releaseId, blob) {
		const body = new FormData();
		body.set('image', blob, 'file.jpg');
		body.set('pos', 2);
		return gmRequest({
			method: 'POST',
			url: `https://www.discogs.com/release/${releaseId}/images/upload`,
			data: body
		}).then(r => {
			if (r.status === 200 && !r.finalUrl.includes('nologin')) {
				return JSON.parse(r.responseText).id;
			}

			return 0;
		}).catch(error => error.message);
	}

	function canvasToBlob(img, quality, compress = true) {
		return new Promise(resolve => {
			const {width, height} = img;

			function toBlob() {
				let canvas = document.createElement('canvas');
				canvas.width = width;
				canvas.height = height;
				const ctx = canvas.getContext('2d');
				ctx.drawImage(img, 0, 0, width, height);
				canvas.toBlob(blob => {
					if (compress && blob.size >= MAX_SIZE) {
						quality -= 0.01;
						return toBlob();
					}

					return resolve(blob);
				}, 'image/jpeg', quality);

				canvas = undefined;
			}

			return toBlob();
		});
	}

	function getImageSize(url) {
		return gmRequest({
			method: 'HEAD',
			url
		}).then(r => {
			const [, bytes] = r.responseHeaders.match(/content-length: (\d+)/);
			return {size: parseInt(bytes, 10)};
		}).catch(error => error.message);
	}

	function getImageObj(url) {
		return new Promise((resolve, reject) => {
			const img = new Image();
			img.crossOrigin = 'anonymous';
			img.src = url;
			img.addEventListener('load', () => {
				resolve(img);
			});

			img.addEventListener('error', e => {
				reject(e);
			});
		});
	}

	function saveAsFile(blob, name) {
		const a = document.createElement('a');
		a.setAttribute('href', URL.createObjectURL(blob));
		a.setAttribute('download', name + '.jpg');
		document.documentElement.append(a);

		const e = new MouseEvent('click');
		a.dispatchEvent(e);

		document.documentElement.removeChild(a);
	}

	function addButton() {
		if (!this.event.isTrusted) {
			return;
		}

		let {target} = this.event;

		if (target.parentNode.querySelector('.save-button')) {
			return;
		}

		let src = '';
		let name = 'cover';

		const a = document.createElement('a');
		const i = document.createElement('i');

		a.className = 'save-button';
		i.className = 'fa fa-download';

		const [, shop] = document.domain.split('.');

		switch (shop) {
			case 'hardtunes':

				if (target.tagName !== 'IMG') {
					return;
				}

				src = target.src;

				if (/248x248/.test(src)) {
					src = src.replace('248x248', 'original');

					a.classList.add('hardtunes-thumbnail');
				} else {
					a.classList.add('hardtunes');
				}

				break;

			case 'hardstyle':

				if (target.tagName === 'DIV' && target.className === 'image') {
					target = target.firstElementChild;
				}

				if (target.tagName !== 'IMG') {
					return;
				}

				a.className = 'save-button';

				src = target.src;

				if (/assets|albums/.test(src)) {
					return;
				}

				src = `https://tracks.content.hardstyle.com/products/${src.replace(/^https:\/\/tracks\.content\.hardstyle\.com\/products\/(\d+)\/(\d+)\/(\d+)[/?][\S\s]*|$/, '$1/$2/$3')}/original.jpg`;

				name = target.alt || name;

				break;

			default:
				break;
		}

		a.setAttribute('role', 'button');
		a.setAttribute('data-src', src);
		a.setAttribute('data-name', name);

		target.parentNode.append(a);
		a.append(i);
	}

	function main() {
		if (!this.event.target.tagName === 'I') {
			return;
		}

		if (!this.event.target.classList.contains('fa-download')) {
			return;
		}

		this.event.preventDefault();

		const {src, name} = this.event.target.parentNode.dataset;
		const upOnDiscogs = this.event.ctrlKey;

		getImageObj(src).then(img => {
			canvasToBlob(img, 0.8).then(blob => {
				if (upOnDiscogs) {
					const ask = prompt('Put release url or id');
					if (!ask) {
						return;
					}

					const id = ask.replace(/[^\d]+/, '');
					if (!id) {
						return;
					}

					uploadImage(id, blob).then(imgid => {
						if (imgid === 0) {
							return notify('Failed upload image. You must be logged!');
						}

						saveImage(id, imgid).then(notify);
					});
				} else {
					saveAsFile(blob, name);
				}
			});
		});
	}

	window.addEventListener('mouseover', addButton, false);

	window.addEventListener('click', main, false);

	document.head.insertAdjacentHTML('beforeend', `
		<style type="text/css">
			.save-button {
				position: absolute;
				z-index: 9999;
				opacity: 0;
				font-size: 24px;
				padding: 4px;
				color: #fff !important;
				border: none;
				background: none;
				background-image: none !important;
				transition: opacity .2s ease-out;
				transition-delay: .1s;
			} .max {
				font-size: 20px;
			} .release-media:hover .save-button, .release-list-item-artwork:hover .save-button, .image:hover .save-button{
				opacity: 1;
			} .fa-download {
				margin: 10px
			} .hardtunes {
                top: 90%;
                left: 10%;
                transform: translate(-50%, -50%);
                font-size: 46px;
            } .hardtunes-thumbnail {
                top: 50%;
                transform: translate(-50%, -50%);
                font-size: 44px;
            }
		</style>`);
})();

